﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
using DefaultScope;
using MediFox.Synchronization.ClientServices.PerstSyncProvider;
using Microsoft.Phone.Controls;
using Microsoft.Synchronization.ClientServices;

namespace PerstSyncProviderTest
{
    public partial class MainPage : PhoneApplicationPage
    {
        private PerstOfflineContext _context;
        private ObservableCollection<string> _logEntries;
        private DateTime _start;

        private readonly Guid _userId = new Guid("418D441C-9AA8-495B-89DD-56C11DB335AF");

        public ObservableCollection<string> LogEntries
        {
            get
            {
                return _logEntries;
            }
        }

        public MainPage()
        {
            InitializeComponent();

            _logEntries = new ObservableCollection<string>();
            _context = ((App)App.Current).OfflineContext;

            DataContext = this;

            ResetButton.IsEnabled = true;
            OpenButton.IsEnabled = true;
            ClearButton.IsEnabled = false;
            SyncButton.IsEnabled = false;
            SelectButton.IsEnabled = false;
            ModifyButton.IsEnabled = false;
            AddButton.IsEnabled = false;
            RemoveButton.IsEnabled = false;
            CloseButton.IsEnabled = false;
        }

        private void OpenButton_Click(object sender, RoutedEventArgs e)
        {
            ResetButton.IsEnabled = false;
            OpenButton.IsEnabled = false;

            Dispatcher dispatcher = this.Dispatcher;
            ThreadPool.QueueUserWorkItem(o =>
                {

                    DateTime start = DateTime.Now;
                    _context = new DefaultScopeOfflineContext("DefaultScope.dbs", new Uri("http://[yourserver]/ListService/DefaultScopeSyncService.svc/"), "secretKey");
                    TimeSpan duration = DateTime.Now.Subtract(start);

                    _context.CacheController.ControllerBehavior.AddScopeParameters("userid", _userId.ToString());
                    _context.CacheController.ControllerBehavior.SerializationFormat = SerializationFormat.ODataJSON;

                    ((App)App.Current).OfflineContext = _context;

                    dispatcher.BeginInvoke(() =>
                        {

                            _logEntries.Insert(0, string.Format("Open: {0} ms", duration.TotalMilliseconds));

                            ClearButton.IsEnabled = true;
                            SyncButton.IsEnabled = true;
                            SelectButton.IsEnabled = true;
                            ModifyButton.IsEnabled = true;
                            AddButton.IsEnabled = true;
                            RemoveButton.IsEnabled = true;
                            CloseButton.IsEnabled = true;
                        });
                });

        }

        private void SyncButton_Click(object sender, RoutedEventArgs e)
        {

            if (!_context.IsActive)
            {
                ClearButton.IsEnabled = false;
                SyncButton.IsEnabled = false;
                SelectButton.IsEnabled = false;
                ModifyButton.IsEnabled = false;
                AddButton.IsEnabled = false;
                RemoveButton.IsEnabled = false;
                CloseButton.IsEnabled = false;

                _context.CacheController.RefreshCompleted += new EventHandler<Microsoft.Synchronization.ClientServices.RefreshCompletedEventArgs>(CacheController_RefreshCompleted);

                _start = DateTime.Now;
                _context.CacheController.RefreshAsync();
            }
        }

        private void SelectButton_Click(object sender, RoutedEventArgs e)
        {
            ClearButton.IsEnabled = false;
            SyncButton.IsEnabled = false;
            SelectButton.IsEnabled = false;
            ModifyButton.IsEnabled = false;
            AddButton.IsEnabled = false;
            RemoveButton.IsEnabled = false;
            CloseButton.IsEnabled = false;

            Dispatcher dispatcher = this.Dispatcher;
            ThreadPool.QueueUserWorkItem(o =>
                {
                    DateTime start = DateTime.Now;
                    IEnumerable<DefaultScope.List> entities = _context.GetCollection<DefaultScope.List>().Where(f => f.Name == "New List");
                    TimeSpan duration = DateTime.Now.Subtract(start);

                    dispatcher.BeginInvoke(() =>
                        {
                            _logEntries.Insert(0, string.Format("Select: {0} ms", duration.TotalMilliseconds));
                        });

                    if (entities != null)
                    {
                        int count = 0;
                        start = DateTime.Now;
                        foreach (DefaultScope.List entity in entities)
                        {
                            count++;
                        }
                        duration = DateTime.Now.Subtract(start);

                        dispatcher.BeginInvoke(() =>
                        {
                            _logEntries.Insert(0, string.Format("Iteration over {0} entities: {1} ms", count, duration.TotalMilliseconds));
                        });

                    }

                    dispatcher.BeginInvoke(() =>
                    {
                        ClearButton.IsEnabled = true;
                        SyncButton.IsEnabled = true;
                        SelectButton.IsEnabled = true;
                        ModifyButton.IsEnabled = true;
                        AddButton.IsEnabled = true;
                        RemoveButton.IsEnabled = true;
                        CloseButton.IsEnabled = true;
                    });
                });

        }

        private void AddButton_Click(object sender, RoutedEventArgs e)
        {
            ClearButton.IsEnabled = false;
            SyncButton.IsEnabled = false;
            SelectButton.IsEnabled = false;
            ModifyButton.IsEnabled = false;
            AddButton.IsEnabled = false;
            RemoveButton.IsEnabled = false;
            CloseButton.IsEnabled = false;

            Dispatcher dispatcher = this.Dispatcher;
            ThreadPool.QueueUserWorkItem(o =>
            {
                DefaultScope.List list = new List()
                {
                    ID = Guid.NewGuid(),
                    UserID = _userId,
                    Name = "New List",
                    Description = "Enter Description.",
                    CreatedDate = DateTime.Now
                };

                DateTime start = DateTime.Now;
                _context.AddItem(list);
                TimeSpan duration = DateTime.Now.Subtract(start);

                dispatcher.BeginInvoke(() =>
                {
                    _logEntries.Insert(0, string.Format("Add: {0} ms", duration.TotalMilliseconds));

                    ClearButton.IsEnabled = true;
                    SyncButton.IsEnabled = true;
                    SelectButton.IsEnabled = true;
                    ModifyButton.IsEnabled = true;
                    AddButton.IsEnabled = true;
                    RemoveButton.IsEnabled = true;
                    CloseButton.IsEnabled = true;
                });
            });
        }

        private void RemoveButton_Click(object sender, RoutedEventArgs e)
        {
            ClearButton.IsEnabled = false;
            SyncButton.IsEnabled = false;
            SelectButton.IsEnabled = false;
            ModifyButton.IsEnabled = false;
            AddButton.IsEnabled = false;
            RemoveButton.IsEnabled = false;
            CloseButton.IsEnabled = false;

            Dispatcher dispatcher = this.Dispatcher;
            ThreadPool.QueueUserWorkItem(o =>
            {
                DefaultScope.List list = _context.GetCollection<DefaultScope.List>().FirstOrDefault();

                if (list != null)
                {
                    DateTime start = DateTime.Now;
                    _context.DeleteItem(list);
                    TimeSpan duration = DateTime.Now.Subtract(start);

                    dispatcher.BeginInvoke(() =>
                    {
                        _logEntries.Insert(0, string.Format("Remove: {0} ms", duration.TotalMilliseconds));
                    });
                }
                else
                {
                    dispatcher.BeginInvoke(() =>
                    {
                        _logEntries.Insert(0, "Remove: allready empty");
                    });
                }

                dispatcher.BeginInvoke(() =>
                {
                    ClearButton.IsEnabled = true;
                    SyncButton.IsEnabled = true;
                    SelectButton.IsEnabled = true;
                    ModifyButton.IsEnabled = true;
                    AddButton.IsEnabled = true;
                    RemoveButton.IsEnabled = true;
                    CloseButton.IsEnabled = true;
                });
            });
        }

        private void ModifyButton_Click(object sender, RoutedEventArgs e)
        {
            ClearButton.IsEnabled = false;
            SyncButton.IsEnabled = false;
            SelectButton.IsEnabled = false;
            ModifyButton.IsEnabled = false;
            AddButton.IsEnabled = false;
            RemoveButton.IsEnabled = false;
            CloseButton.IsEnabled = false;

            Dispatcher dispatcher = this.Dispatcher;
            ThreadPool.QueueUserWorkItem(o =>
            {
                DefaultScope.List list = _context.GetCollection<DefaultScope.List>().FirstOrDefault();

                if (list != null)
                {
                    DateTime start = DateTime.Now;
                    list.Name = "Different Name";
                    TimeSpan duration = DateTime.Now.Subtract(start);

                    dispatcher.BeginInvoke(() =>
                    {
                        _logEntries.Insert(0, string.Format("Modify: {0} ms", duration.TotalMilliseconds));
                    });
                }
                else
                {
                    dispatcher.BeginInvoke(() =>
                    {
                        _logEntries.Insert(0, "Modify: empty");
                    });
                }

                dispatcher.BeginInvoke(() =>
                {
                    ClearButton.IsEnabled = true;
                    SyncButton.IsEnabled = true;
                    SelectButton.IsEnabled = true;
                    ModifyButton.IsEnabled = true;
                    AddButton.IsEnabled = true;
                    RemoveButton.IsEnabled = true;
                    CloseButton.IsEnabled = true;
                });
            });
        }

        private void ClearButton_Click(object sender, RoutedEventArgs e)
        {
            ClearButton.IsEnabled = false;
            SyncButton.IsEnabled = false;
            SelectButton.IsEnabled = false;
            ModifyButton.IsEnabled = false;
            AddButton.IsEnabled = false;
            RemoveButton.IsEnabled = false;
            CloseButton.IsEnabled = false;

            Dispatcher dispatcher = this.Dispatcher;
            ThreadPool.QueueUserWorkItem(o =>
            {

                DateTime start = DateTime.Now;
                _context.ClearCache();
                TimeSpan duration = DateTime.Now.Subtract(start);

                dispatcher.BeginInvoke(() =>
                    {
                        _logEntries.Insert(0, string.Format("Clear: {0} ms", duration.TotalMilliseconds));

                        SyncButton.IsEnabled = true;
                        CloseButton.IsEnabled = true;
                    });
            });
        }

        private void CloseButton_Click(object sender, RoutedEventArgs e)
        {

            ClearButton.IsEnabled = false;
            SyncButton.IsEnabled = false;
            SelectButton.IsEnabled = false;
            ModifyButton.IsEnabled = false;
            AddButton.IsEnabled = false;
            RemoveButton.IsEnabled = false;
            CloseButton.IsEnabled = false;

            Dispatcher dispatcher = this.Dispatcher;
            ThreadPool.QueueUserWorkItem(o =>
            {

                DateTime start = DateTime.Now;
                _context.Dispose();
                TimeSpan duration = DateTime.Now.Subtract(start);

                _context = null;
                ((App)App.Current).OfflineContext = null;

                dispatcher.BeginInvoke(() =>
                    {
                        _logEntries.Insert(0, string.Format("Close: {0} ms", duration.TotalMilliseconds));
                        ResetButton.IsEnabled = true;
                        OpenButton.IsEnabled = true;
                    });
            });

        }

        private void CacheController_RefreshCompleted(object sender, Microsoft.Synchronization.ClientServices.RefreshCompletedEventArgs e)
        {
            TimeSpan duration = DateTime.Now.Subtract(_start);

            int count = (int)e.Statistics.TotalDownloads;

            _logEntries.Insert(0, string.Format("Sync of {0} records: {1} ms", count, duration.TotalMilliseconds));

            CacheController cacheController = sender as CacheController;
            cacheController.RefreshCompleted -= CacheController_RefreshCompleted;

            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message, "Sync Error", MessageBoxButton.OK);
            }

            ClearButton.IsEnabled = true;
            SelectButton.IsEnabled = true;
            SyncButton.IsEnabled = true;
            ModifyButton.IsEnabled = true;
            AddButton.IsEnabled = true;
            RemoveButton.IsEnabled = true;
            CloseButton.IsEnabled = true;
        }

        private void ResetButton_Click(object sender, RoutedEventArgs e)
        {
            using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
            {
                try
                {
                    foreach (string file in store.GetFileNames())
                    {
                        store.DeleteFile(file);
                    }
                    foreach (string dir in store.GetDirectoryNames())
                    {
                        ClearDirectory(store, ".");
                        store.DeleteDirectory(dir);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, ex.GetType().Name, MessageBoxButton.OK);
                }
            }
        }

        private static void ClearDirectory(IsolatedStorageFile store, string path)
        {
            string pattern = Path.Combine(path, "*");
            foreach (string fileName in store.GetFileNames(pattern))
            {
                string filePath = Path.Combine(path, fileName);
                store.DeleteFile(filePath);
            }
            foreach (string dir in store.GetDirectoryNames(pattern))
            {
                string subdir = Path.Combine(path, dir);
                ClearDirectory(store, subdir);
                store.DeleteDirectory(subdir);
            }
        }


    }
}